package com.gitee.qdbp.general.system.biz.personnel.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.controlling.DataIsolationTools;
import com.gitee.qdbp.base.controlling.IDataIsolationControlling;
import com.gitee.qdbp.base.enums.Gender;
import com.gitee.qdbp.base.enums.OperateType;
import com.gitee.qdbp.base.model.consts.Keys;
import com.gitee.qdbp.base.system.model.IAccount;
import com.gitee.qdbp.base.system.model.IAccountType;
import com.gitee.qdbp.base.system.service.IPasswordService;
import com.gitee.qdbp.general.common.api.files.model.FolderName;
import com.gitee.qdbp.general.common.api.files.model.PathParams;
import com.gitee.qdbp.general.common.api.files.service.IWebFileService;
import com.gitee.qdbp.general.common.api.sequence.service.ILocalSequenceGenerator;
import com.gitee.qdbp.general.system.api.permission.basic.IUserRoleRefBasic;
import com.gitee.qdbp.general.system.api.permission.model.UserRoleRefBean;
import com.gitee.qdbp.general.system.api.permission.model.UserRoleRefWhere;
import com.gitee.qdbp.general.system.api.personnel.basic.IDepartmentCoreBasic;
import com.gitee.qdbp.general.system.api.personnel.basic.IUserCoreBasic;
import com.gitee.qdbp.general.system.api.personnel.convert.IUserSourceConverter;
import com.gitee.qdbp.general.system.api.personnel.model.AccountBean;
import com.gitee.qdbp.general.system.api.personnel.model.DepartmentCoreBean;
import com.gitee.qdbp.general.system.api.personnel.model.DepartmentCoreWhere;
import com.gitee.qdbp.general.system.api.personnel.model.UserCoreBean;
import com.gitee.qdbp.general.system.api.personnel.model.UserCoreUpdate;
import com.gitee.qdbp.general.system.api.personnel.model.UserCoreWhere;
import com.gitee.qdbp.general.system.api.personnel.service.IUserCoreExecutor;
import com.gitee.qdbp.general.system.enums.UserState;
import com.gitee.qdbp.general.system.error.UserErrorCode;
import com.gitee.qdbp.tools.utils.ConvertTools;
import com.gitee.qdbp.tools.utils.JsonTools;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 用户基础信息业务处理类
 *
 * @author zhh
 * @version 170215
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public class UserCoreExecutor implements IUserCoreExecutor {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(UserCoreExecutor.class);

    @Autowired
    private IUserCoreBasic userCoreBasic;
    @Autowired
    private IDepartmentCoreBasic departmentCoreBasic;
    @Autowired
    private IUserRoleRefBasic userRoleRefBasic;
    @Autowired
    private IPasswordService passwordService;
    @Autowired
    private IUserSourceConverter userSourceConverter;
    @Autowired
    private ILocalSequenceGenerator sequenceGenerator;
    @Autowired
    private IDataIsolationControlling dataIsolationControlling;
    @Autowired
    private IWebFileService webFileService;

    // 将文件从临时路径复制到正式路径
    protected String copyRegisterFileToFormalFolder(String url, String tenantCode, String userId)
            throws ServiceException {
        Map<String, Object> map = new HashMap<>();
        map.put("tenant-code", tenantCode);
        map.put("user-id", userId);
        PathParams options = new PathParams();
        options.setFolder(FolderName.files.name());
        options.setExtra(map);
        return webFileService.moveTo(url, options);
    }

    // 将文件从临时路径复制到正式路径, 同时删除被替换掉的文件
    protected String copyUpdateFileToFormalFolder(String tempUrl, String oldUrl) throws ServiceException {
        // 将文件从临时路径复制到正式路径
        String newUrl = webFileService.moveTo(tempUrl, FolderName.files);
        // 删除之前的头像
        if (VerifyTools.isNotBlank(oldUrl)) {
            try {
                webFileService.deleteFile(oldUrl);
            } catch (ServiceException ignore) {
            }
        }
        return newUrl;
    }

    @Override
    public void create(UserCoreBean model, List<String> roleIds, IAccount me) throws ServiceException {
        String msg = "Failed to create UserCore. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 由于保存用户头像图片需要用到tenantCode, 因此需要先处理数据隔离
        dataIsolationControlling.handle(model, OperateType.CREATE, "tenantCode");
        String tenantCode = model.getTenantCode();
        IAccountType userType = model.getUserType();
        // 验证: 工号/手机/邮箱不能同时为空
        String userCode = model.getUserCode();
        String phone = model.getPhone();
        String email = model.getEmail();
        String userName = model.getUserName();
        // 不能同时为空
        if (VerifyTools.isAllBlank(userCode, phone, email)) {
            log.warn("工号/手机/邮箱不能同时为空" + JsonTools.newlineLogs(model));
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        // 部门编号不能为空
        String deptCode = model.getDeptCode();
        if (VerifyTools.isBlank(deptCode)) {
            deptCode = Keys.ROOT_CODE;
        }

        if (!Keys.ROOT_CODE.equals(deptCode)) { // 验证: 部门是否存在
            DepartmentCoreWhere where = new DepartmentCoreWhere();
            where.setDeptCode(deptCode);
            DepartmentCoreBean dept = departmentCoreBasic.find(where);
            if (dept == null) {
                log.error(msg + "department not found: {}", deptCode);
                throw new ServiceException(ResultCode.PARAMETER_VALUE_ERROR);
            }
        }

        // 检查手机号码/用户工号/登录名的唯一性
        if (VerifyTools.isNotBlank(phone)) {
            checkPhoneThrowOnAlreadyExists(new AccountBean(tenantCode, userType, phone), null);
        }
        if (VerifyTools.isNotBlank(email)) {
            checkEmailThrowOnAlreadyExists(new AccountBean(tenantCode, userType, email), null);
        }
        if (VerifyTools.isNotBlank(userCode)) {
            checkUserCodeThrowOnAlreadyExists(new AccountBean(tenantCode, userType, userCode), null);
        }
        if (VerifyTools.isNotBlank(userName)) {
            checkUserNameThrowOnAlreadyExists(new AccountBean(tenantCode, userType, userName), null);
        }

        String userId = sequenceGenerator.generate(UserCoreBean.TABLE);
        model.setId(userId); // 生成新的ID
        // 将文件从临时路径复制到正式路径
        if (VerifyTools.isNotBlank(model.getPhoto())) {
            model.setPhoto(copyRegisterFileToFormalFolder(model.getPhoto(), tenantCode, userId));
        }
        if (VerifyTools.isBlank(model.getUserState())) {
            model.setUserState(UserState.NORMAL); // 状态置为正常
        }

        if (VerifyTools.isBlank(model.getPassword())) {
            model.setPassword("@PASSWORD"); // 如果没有密码, 默认设置为@PASSWORD
        }
        model.setPassword(passwordService.create(userId, model.getPassword()));
        model.setSuperman(false); // 超级管理员置为false(超级管理员只能预置,不允许创建)
        model.setTenantCode(tenantCode); // 重置租户编号

        if (VerifyTools.isBlank(model.getGender())) {
            model.setGender(Gender.UNKNOWN);
        }
        if (VerifyTools.isBlank(model.getDeptCode())) {
            model.setDeptCode(Keys.ROOT_CODE); // 部门编号如果为空, 设为0
        }
        if (model.getUserSource() == null) {
            model.setUserSource(userSourceConverter.getDefaults());
        }

        // 向sys_user_core_info表插入记录
        userCoreBasic.create(model);

        // 创建角色关联
        if (VerifyTools.isNotBlank(roleIds)) {
            doDistributeRoles(userId, roleIds, me);
        }

    }

    @Override
    public void update(UserCoreUpdate model, IAccount me) throws ServiceException {
        update(model, null, me);
    }

    @Override
    public void update(UserCoreUpdate model, List<String> roleIds, IAccount me) throws ServiceException {
        String msg = "Failed to update UserCore. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String id = model.getId();
        if (VerifyTools.isBlank(id) && model.getWhere() != null) {
            id = model.getWhere().getId();
        }
        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 原始记录检查
        UserCoreBean older = userCoreBasic.findById(id);
        if (older == null) {
            log.error(msg + "record is not found. id=" + id);
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }

        String tenantCode = older.getTenantCode();
        IAccountType userType = older.getUserType();
        UserCoreUpdate newer = createChangedModel(model, older);

        if (newer != null) {
            // 检查手机号码/用户工号/登录名的唯一性
            if (VerifyTools.isNotBlank(newer.getPhone())) {
                checkPhoneThrowOnAlreadyExists(new AccountBean(tenantCode, userType, newer.getPhone()), id);
            }
            if (VerifyTools.isNotBlank(newer.getEmail())) {
                checkPhoneThrowOnAlreadyExists(new AccountBean(tenantCode, userType, newer.getEmail()), id);
            }
            if (VerifyTools.isNotBlank(newer.getUserCode())) {
                checkPhoneThrowOnAlreadyExists(new AccountBean(tenantCode, userType, newer.getUserCode()), id);
            }
            if (VerifyTools.isNotBlank(newer.getUserName())) {
                checkPhoneThrowOnAlreadyExists(new AccountBean(tenantCode, userType, newer.getUserName()), id);
            }
            // 将文件从临时路径复制到正式路径
            if (VerifyTools.isNotBlank(newer.getPhoto())) {
                // 将文件从临时路径复制到正式路径
                newer.setPhoto(copyUpdateFileToFormalFolder(newer.getPhoto(), older.getPhoto()));
            }

            // 更新sys_user_core_info表的记录
            userCoreBasic.update(newer, false);
        }

        // 修改角色关联
        if (roleIds != null) { // roleIds=null不修改角色,roleIds.size=0则清空所有角色
            doDistributeRoles(id, roleIds, me);
        }
    }

    @Override
    public void delete(String id, IAccount me) throws ServiceException {
        String msg = "Failed to delete UserCore. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 从sys_user_core_info表查询原记录
        UserCoreBean older = userCoreBasic.findById(id);
        if (older == null) {
            log.error(msg + "record is not found.\n\tid is " + id);
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }

        // 删除用户角色关联
        UserRoleRefWhere where = new UserRoleRefWhere();
        where.setUserId(id);
        userRoleRefBasic.delete(where, false);

        // 删除sys_user_core_info表的记录
        userCoreBasic.deleteByIds(ConvertTools.toList(id), false);
    }

    @Override
    public void delete(List<String> ids, IAccount me) throws ServiceException {
        String msg = "Failed to delete UserCore. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(ids)) {
            log.error(msg + "params is null: ids");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 删除用户角色关联
        UserRoleRefWhere where = new UserRoleRefWhere();
        where.setUserIds(ids);
        userRoleRefBasic.delete(where, false);

        // 删除sys_user_core_info表的记录
        userCoreBasic.deleteByIds(ids, false);
    }

    @Override
    public void delete(UserCoreWhere where, IAccount me) throws ServiceException {
        String msg = "Failed to delete UserCore. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(where)) {
            log.error(msg + "params is null: where");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        Set<String> temp = new HashSet<>();
        { // 根据条件查询UserId
            PageList<UserCoreBean> PageList = userCoreBasic.list(where, OrderPaging.NONE);
            if (VerifyTools.isBlank(PageList)) {
                return;
            }
            for (UserCoreBean user : PageList) {
                temp.add(user.getId());
            }
        }

        List<String> ids = new ArrayList<>(temp);
        // 删除用户角色关联
        UserRoleRefWhere rw = new UserRoleRefWhere();
        rw.setUserIds(ids);
        userRoleRefBasic.delete(rw, false);

        // 删除sys_user_core_info表的记录
        userCoreBasic.deleteByIds(ids, false);
    }

    @Override
    public void distributeRoles(String userId, List<String> roleIds, IAccount me) throws ServiceException {

        if (VerifyTools.isBlank(userId)) {
            log.warn("参数不能为空: userId");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (roleIds == null) { // roleIds=null报错, roleIds.size=0则清空所有角色
            log.warn("参数不能为空: roleIds");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(me)) {
            log.warn("参数不能为空: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 重新分配角色关系
        doDistributeRoles(userId, roleIds, me);
    }

    private void doDistributeRoles(String userId, List<String> roleIds, IAccount me) throws ServiceException {

        if (roleIds.isEmpty()) {
            // roleIds.size=0则清空所有角色
            UserRoleRefWhere where = new UserRoleRefWhere();
            where.setUserId(userId);
            userRoleRefBasic.delete(where, false);
            return;
        }

        // 查询该用户原有的角色
        PageList<UserRoleRefBean> old;
        {
            UserRoleRefWhere where = new UserRoleRefWhere();
            where.setUserId(userId);
            old = userRoleRefBasic.list(where, OrderPaging.NONE);
        }

        // 查找数据库不存在的, 就是需要增加的
        Set<String> needAddList = new HashSet<>();
        // 数据库比传入参数多的, 就是需要删除的
        Set<String> needDelList = new HashSet<>();

        Map<String, UserRoleRefBean> map = new HashMap<>();
        if (VerifyTools.isNotBlank(old)) {
            for (UserRoleRefBean i : old) {
                map.put(i.getRoleId(), i);
                if (roleIds.indexOf(i.getRoleId()) < 0) {
                    needDelList.add(i.getRoleId());
                }
            }
        }

        for (String roleId : roleIds) {
            if (!map.containsKey(roleId)) {
                needAddList.add(roleId);
            }
        }

        // 创建需要增加的
        if (VerifyTools.isNotBlank(needAddList)) {
            for (String roleId : needAddList) {
                UserRoleRefBean model = new UserRoleRefBean();
                model.setUserId(userId);
                model.setRoleId(roleId);
                userRoleRefBasic.create(model);
            }
        }

        // 删除数据库多的
        if (VerifyTools.isNotBlank(needDelList)) {
            UserRoleRefWhere where = new UserRoleRefWhere();
            where.setUserId(userId);
            where.setRoleIds(new ArrayList<>(needDelList));
            userRoleRefBasic.delete(where, false);
        }
    }

    @Override
    public void checkPhoneThrowOnAlreadyExists(AccountBean model, String userId) throws ServiceException {
        String msg = "Failed to CheckPhone. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setPhone(model.getAccount());
        // 用户唯一性校验, 需要全局查询
        DataIsolationTools.disable("deptCode");
        PageList<UserCoreBean> beans = userCoreBasic.list(where, OrderPaging.NONE);
        DataIsolationTools.enable("deptCode");
        if (userId == null) {
            if (beans.getTotal() > 0) {
                log.error("Phone[{}] has registered.", model.getAccount());
                throw new ServiceException(UserErrorCode.PHONE_HAS_REGISTER);
            }
        } else {
            for (UserCoreBean bean : beans) {
                if (!bean.getId().equals(userId)) {
                    log.error("Phone[{}] has registered.", model.getAccount());
                    throw new ServiceException(UserErrorCode.PHONE_HAS_REGISTER);
                }
            }
        }
    }

    @Override
    public void checkEmailThrowOnAlreadyExists(AccountBean model, String userId) throws ServiceException {
        String msg = "Failed to CheckEmail. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setEmail(model.getAccount());
        // 用户唯一性校验, 需要全局查询
        DataIsolationTools.disable("deptCode");
        PageList<UserCoreBean> beans = userCoreBasic.list(where, OrderPaging.NONE);
        DataIsolationTools.enable("deptCode");
        if (userId == null) {
            if (beans.getTotal() > 0) {
                log.error("Email[{}] has registered.", model.getAccount());
                throw new ServiceException(UserErrorCode.EMAIL_HAS_REGISTER);
            }
        } else {
            for (UserCoreBean bean : beans) {
                if (!bean.getId().equals(userId)) {
                    log.error("Email[{}] has registered.", model.getAccount());
                    throw new ServiceException(UserErrorCode.EMAIL_HAS_REGISTER);
                }
            }
        }
    }

    @Override
    public void checkUserCodeThrowOnAlreadyExists(AccountBean model, String userId) throws ServiceException {
        String msg = "Failed to CheckUserCode. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setUserCode(model.getAccount());
        // 用户唯一性校验, 需要全局查询
        DataIsolationTools.disable("deptCode");
        PageList<UserCoreBean> beans = userCoreBasic.list(where, OrderPaging.NONE);
        DataIsolationTools.enable("deptCode");
        if (userId == null) {
            if (beans.getTotal() > 0) {
                log.error("UserCode[{}] has registered.", model.getAccount());
                throw new ServiceException(UserErrorCode.USER_HAS_REGISTER);
            }
        } else {
            for (UserCoreBean bean : beans) {
                if (!bean.getId().equals(userId)) {
                    log.error("UserCode[{}] has registered.", model.getAccount());
                    throw new ServiceException(UserErrorCode.USER_HAS_REGISTER);
                }
            }
        }
    }

    @Override
    public void checkUserNameThrowOnAlreadyExists(AccountBean model, String userId) throws ServiceException {
        String msg = "Failed to CheckUserName. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setUserName(model.getAccount());
        // 用户唯一性校验, 需要全局查询
        DataIsolationTools.disable("deptCode");
        PageList<UserCoreBean> beans = userCoreBasic.list(where, OrderPaging.NONE);
        DataIsolationTools.enable("deptCode");
        if (userId == null) {
            if (beans.getTotal() > 0) {
                log.error("UserName[{}] has registered.", model.getAccount());
                throw new ServiceException(UserErrorCode.USER_HAS_REGISTER);
            }
        } else {
            for (UserCoreBean bean : beans) {
                if (!bean.getId().equals(userId)) {
                    log.error("UserName[{}] has registered.", model.getAccount());
                    throw new ServiceException(UserErrorCode.USER_HAS_REGISTER);
                }
            }
        }
    }

    /** 根据ID查找用户，如果用户不存在则报错 **/
    @Override
    public UserCoreBean findByIdThrowOnNotExists(String id) throws ServiceException {
        String msg = "Failed to FindUserById. ";

        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setId(id);
        UserCoreBean user = userCoreBasic.find(where);
        if (user != null) {
            return user;
        } else {
            log.error(msg + "user info not found, id={}", id);
            throw new ServiceException(UserErrorCode.USER_NOT_EXIST);
        }
    }

    /** 根据手机号码查找用户，如果用户不存在则报错 **/
    @Override
    public UserCoreBean findByPhoneThrowOnNotExists(AccountBean model) throws ServiceException {
        String msg = "Failed to FindUserByPhone. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setPhone(model.getAccount());
        UserCoreBean user = userCoreBasic.find(where);
        if (user != null) {
            return user;
        } else {
            log.error(msg + "user info not found, phone={}", model.getAccount());
            throw new ServiceException(UserErrorCode.USER_NOT_EXIST);
        }
    }

    /** 根据邮箱地址查找用户，如果用户不存在则报错 **/
    @Override
    public UserCoreBean findByEmailThrowOnNotExists(AccountBean model) throws ServiceException {
        String msg = "Failed to FindUserByEmail. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setEmail(model.getAccount());
        UserCoreBean user = userCoreBasic.find(where);
        if (user != null) {
            return user;
        } else {
            log.error(msg + "user info not found, email={}", model.getAccount());
            throw new ServiceException(UserErrorCode.USER_NOT_EXIST);
        }
    }

    /** 根据用户工号查找用户，如果用户不存在则报错 **/
    @Override
    public UserCoreBean findByUserCodeThrowOnNotExists(AccountBean model) throws ServiceException {
        String msg = "Failed to FindUserByUserCode. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setUserCode(model.getAccount());
        UserCoreBean user = userCoreBasic.find(where);
        if (user != null) {
            return user;
        } else {
            log.error(msg + "user info not found, UserCode={}", model.getAccount());
            throw new ServiceException(UserErrorCode.USER_NOT_EXIST);
        }
    }

    /** 根据用户登录名查找用户，如果用户不存在则报错 **/
    @Override
    public UserCoreBean findByUserNameThrowOnNotExists(AccountBean model) throws ServiceException {
        String msg = "Failed to FindUserByUserName. ";

        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAccount())) {
            log.error(msg + "params is null: account");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        UserCoreWhere where = new UserCoreWhere();
        where.setTenantCode(model.getFactory());
        where.setUserType(model.getType());
        where.setUserName(model.getAccount());
        UserCoreBean user = userCoreBasic.find(where);
        if (user != null) {
            return user;
        } else {
            log.error(msg + "user info not found, UserName={}", model.getAccount());
            throw new ServiceException(UserErrorCode.USER_NOT_EXIST);
        }
    }

    /**
     * 创建一个新的对象, 只包含改动过的字段
     *
     * @author zhh
     * @param model 目标对象(一般是参数传入的)
     * @param older 源对象(一般是从数据库查询得到的)
     * @return 只包含有更新的字段对象
     */
    private UserCoreUpdate createChangedModel(UserCoreUpdate model, UserCoreBean older) {
        UserCoreUpdate newer = new UserCoreUpdate();
        newer.setWhere(model.getWhere());

        boolean changed = false;
        newer.setId(model.getId()); // 用户ID

        // if (VerifyTools.isChanged(model.getTenantCode(), older.getTenantCode())) {
        //     changed = true;
        //     newer.setTenantCode(model.getTenantCode()); // 租户编号
        // }
        // if (VerifyTools.isChanged(model.getUserType(), older.getUserType())) {
        //     changed = true;
        //     newer.setUserType(model.getUserType()); // 用户类型
        // }
        if (VerifyTools.isChanged(model.getDeptCode(), older.getDeptCode())) {
            changed = true;
            newer.setDeptCode(model.getDeptCode()); // 部门编号
        }
        if (VerifyTools.isChanged(model.getUserCode(), older.getUserCode())) {
            changed = true;
            newer.setUserCode(model.getUserCode()); // 账号/工号
        }
        if (VerifyTools.isChanged(model.getUserName(), older.getUserName())) {
            changed = true;
            newer.setUserName(model.getUserName()); // 登录用户名
        }
        if (VerifyTools.isChanged(model.getNickName(), older.getNickName())) {
            changed = true;
            newer.setNickName(model.getNickName()); // 昵称
        }
        if (VerifyTools.isChanged(model.getRealName(), older.getRealName())) {
            changed = true;
            newer.setRealName(model.getRealName()); // 真实姓名
        }
        if (VerifyTools.isChanged(model.getPhone(), older.getPhone())) {
            changed = true;
            newer.setPhone(model.getPhone()); // 电话
        }
        if (VerifyTools.isChanged(model.getEmail(), older.getEmail())) {
            changed = true;
            newer.setEmail(model.getEmail()); // 邮箱
        }
        if (VerifyTools.isChanged(model.getGender(), older.getGender())) {
            changed = true;
            newer.setGender(model.getGender()); // 性别(0.未知|1.男|2.女)
        }
        if (VerifyTools.isChanged(model.getPhoto(), older.getPhoto())) {
            changed = true;
            newer.setPhoto(model.getPhoto()); // 头像
        }
        if (VerifyTools.isChanged(model.getCity(), older.getCity())) {
            changed = true;
            newer.setCity(model.getCity()); // 城市
        }
        if (VerifyTools.isChanged(model.getIdentity(), older.getIdentity())) {
            changed = true;
            newer.setIdentity(model.getIdentity()); // 身份证
        }
        // if (VerifyTools.isChanged(model.getPassword(), older.getPassword())) {
        //     changed = true;
        //     newer.setPassword(model.getPassword()); // 密码
        // }
        // if (VerifyTools.isChanged(model.getCreateTime(), older.getCreateTime())) {
        //     changed = true;
        //     newer.setCreateTime(model.getCreateTime()); // 创建时间
        // }
        // if (VerifyTools.isChanged(model.getSuperman(), older.getSuperman())) {
        //     changed = true;
        //     newer.setSuperman(model.getSuperman()); // 是否为超级用户
        // }
        // if (VerifyTools.isChanged(model.getUserState(), older.getUserState())) {
        //     changed = true;
        //     newer.setUserState(model.getUserState()); // 状态(0.正常|1.锁定|2.待激活|3.注销)
        // }
        // if (VerifyTools.isChanged(model.getUserSource(), older.getUserSource())) {
        //     changed = true;
        //     newer.setUserSource(model.getUserSource()); // 来源(0.未知|1.录入)
        // }
        if (VerifyTools.isChanged(model.getOptions(), older.getOptions())) {
            changed = true;
            newer.setOptions(model.getOptions()); // 选项
        }
        // if (VerifyTools.isChanged(model.getDataState(), older.getDataState())) {
        //     changed = true;
        //     newer.setDataState(model.getDataState()); // 数据状态:0为正常|其他为删除
        // }
        // if (Boolean.TRUE.equals(model.isTenantCodeToNull())) {
        //     changed = true;
        //     newer.setTenantCodeToNull(true); // 租户编号更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isUserTypeToNull())) {
        //     changed = true;
        //     newer.setUserTypeToNull(true); // 用户类型更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isDeptCodeToNull())) {
        //     changed = true;
        //     newer.setDeptCodeToNull(true); // 部门编号更新为空值
        // }
        if (Boolean.TRUE.equals(model.isUserCodeToNull())) {
            changed = true;
            newer.setUserCodeToNull(true); // 账号/工号更新为空值
        }
        if (Boolean.TRUE.equals(model.isUserNameToNull())) {
            changed = true;
            newer.setUserNameToNull(true); // 登录用户名更新为空值
        }
        if (Boolean.TRUE.equals(model.isNickNameToNull())) {
            changed = true;
            newer.setNickNameToNull(true); // 昵称更新为空值
        }
        if (Boolean.TRUE.equals(model.isRealNameToNull())) {
            changed = true;
            newer.setRealNameToNull(true); // 真实姓名更新为空值
        }
        if (Boolean.TRUE.equals(model.isPhoneToNull())) {
            changed = true;
            newer.setPhoneToNull(true); // 电话更新为空值
        }
        if (Boolean.TRUE.equals(model.isEmailToNull())) {
            changed = true;
            newer.setEmailToNull(true); // 邮箱更新为空值
        }
        // if (Boolean.TRUE.equals(model.isGenderToNull())) {
        //     changed = true;
        //     newer.setGenderToNull(true); // 性别(0.未知|1.男|2.女)更新为空值
        // }
        if (Boolean.TRUE.equals(model.isPhotoToNull())) {
            changed = true;
            newer.setPhotoToNull(true); // 头像更新为空值
        }
        if (Boolean.TRUE.equals(model.isCityToNull())) {
            changed = true;
            newer.setCityToNull(true); // 城市更新为空值
        }
        if (Boolean.TRUE.equals(model.isIdentityToNull())) {
            changed = true;
            newer.setIdentityToNull(true); // 身份证更新为空值
        }
        // if (Boolean.TRUE.equals(model.isPasswordToNull())) {
        //     changed = true;
        //     newer.setPasswordToNull(true); // 密码更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isSupermanToNull())) {
        //     changed = true;
        //     newer.setSupermanToNull(true); // 是否为超级用户更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isUserStateToNull())) {
        //     changed = true;
        //     newer.setUserStateToNull(true); // 状态(0.正常|1.锁定|2.待激活|3.注销)更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isUserSourceToNull())) {
        //     changed = true;
        //     newer.setUserSourceToNull(true); // 来源(0.未知|1.录入)更新为空值
        // }
        if (Boolean.TRUE.equals(model.isOptionsToNull())) {
            changed = true;
            newer.setOptionsToNull(true); // 选项更新为空值
        }
        return changed ? newer : null;
    }

}
